﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using BEPUphysics;
using Microsoft.Xna.Framework;
using PloobsEngine.Physic.PhysicObjects.BepuObject;
using Microsoft.Xna.Framework.Graphics;

namespace PloobsEngine.Modelo
{
    public class SimpleTerrainModel : IModelo
    {
        public SimpleTerrainModel(TerrainObject to)
        {
            this.terrain = to;
        }

        public SimpleTerrainModel(TerrainObject to,String basetexture)
        {
            this.terrain = to;
            this.basetexture = basetexture;
        }


        public SimpleTerrainModel(TerrainObject to, String basetexture, String nivelBaixo, String nivelMedio,String nivelAlto)
        {
            this.terrain = to;
            this.basetexture = basetexture;
            this.nivelAlto = nivelAlto;
            this.nivelBaixo = nivelBaixo;
            this.nivelMedio = nivelMedio;
        }      
        
        String nivelBaixo;
        String nivelMedio;
        String nivelAlto;
        string basetexture;
        Texture2D difuse;
        Texture2D nb;
        Texture2D nm;
        Texture2D na;

        #region IModelo Members

        TerrainObject terrain;
        BatchInformation[][] batchInformationS = new BatchInformation[1][];
        VertexBuffer[] vertexBufferS = new VertexBuffer[1];
        IndexBuffer[] indexBufferS = new IndexBuffer[1];

        public void LoadModelo()
        {
            
            List<VertexPositionNormalTexture> vertexList = new List<VertexPositionNormalTexture>();
            List<int> indexList = new List<int>();
            GetVertexData(vertexList, indexList, terrain);

            var newVertices = new VertexPositionNormalTexture[vertexList.Count];
            vertexList.CopyTo(newVertices);            

            var newIndices = new int[indexList.Count];
            indexList.CopyTo(newIndices);            

            vertexBufferS[0] = new VertexBuffer(EngineStuff.GraphicsDevice, newVertices.Length * VertexPositionNormalTexture.SizeInBytes, BufferUsage.WriteOnly);
            vertexBufferS[0].SetData(newVertices);
            indexBufferS[0] = new IndexBuffer(EngineStuff.GraphicsDevice, newIndices.Length * 4, BufferUsage.WriteOnly, IndexElementSize.ThirtyTwoBits);
            indexBufferS[0].SetData(newIndices);

            BatchInformation bi = new BatchInformation(0, vertexList.Count, indexList.Count / 3, 0, 0, new VertexDeclaration(EngineStuff.GraphicsDevice, VertexPositionNormalTexture.VertexElements), VertexPositionNormalTexture.SizeInBytes);
            batchInformationS[0] = new BatchInformation[1];
            batchInformationS[0][0] = bi;

            if (!String.IsNullOrEmpty(basetexture))
            {
                difuse = EngineStuff.CustomContentManager.GetAsset<Texture2D>(basetexture);
            }
            if (!String.IsNullOrEmpty(nivelBaixo))
            {
                nb = EngineStuff.CustomContentManager.GetAsset<Texture2D>(nivelBaixo);
            }
            if (!String.IsNullOrEmpty(nivelAlto))
            {
                na = EngineStuff.CustomContentManager.GetAsset<Texture2D>(nivelAlto);
            }
            if (!String.IsNullOrEmpty(nivelMedio))
            {
                nm = EngineStuff.CustomContentManager.GetAsset<Texture2D>(nivelMedio);
            }
 
        }

        public void Serialize(System.Xml.XmlTextWriter textWriter)
        {         
        }

        public void DeSerialize(System.Xml.XmlNode node, EngineStuff engine)
        {            
        }

        public object getModelTag()
        {
            return null;
        }

        public Microsoft.Xna.Framework.Graphics.ModelMesh[] getModelMeshes()
        {
            return null;   
        }

        Matrix[] m = new Matrix[] {Matrix.Identity};
        public Microsoft.Xna.Framework.Matrix[] getBonesTransformation()
        {
            return m;
        }
        
        public Microsoft.Xna.Framework.Graphics.Texture2D getTexture(TextureType textureType)
        {
            switch (textureType)
            {
                case TextureType.DIFFUSE:
                    return difuse;                    
                case TextureType.SPECULAR:
                    break;
                case TextureType.BUMP:
                    break;
                case TextureType.GLOW:
                    break;
                case TextureType.PARALAX:
                    break;
                case TextureType.MULTITEX1:
                    return nb;
                case TextureType.MULTITEX2:
                    return nm;
                case TextureType.MULTITEX3:
                    return na;
                default:
                    break;
            }
            throw new Exception("Wrong type");
            
        }

        public Microsoft.Xna.Framework.BoundingSphere GetBoudingSphere()
        {
            throw new NotImplementedException();
        }

        public int MeshNumber
        {
            get { return 1; }
        }

        public Microsoft.Xna.Framework.Graphics.VertexBuffer GetVertexBuffer(int meshNumber)
        {
            return vertexBufferS[0];
        }

        public Microsoft.Xna.Framework.Graphics.IndexBuffer GetIndexBuffer(int meshNumber)
        {
            return indexBufferS[0];
        }

        public BatchInformation[] GetBatchInformation(int meshNumber)
        {
            return batchInformationS[0];
        }

        String nome = null;
        public string Name
        {
            get
            {
                return nome;
            }
            set
            {
                this.nome = value;
            }
        }

        private void GetVertexData(List<VertexPositionNormalTexture> vertices, List<int> indices, TerrainObject terrain)
        {
            Terrain DisplayedObject = terrain.Terrain;
            Vector3 normal;
            int numColumns = DisplayedObject.Heights.GetLength(0);
            int numRows = DisplayedObject.Heights.GetLength(1);
            for (int i = 0; i < numColumns; i++)
            {
                for (int j = 0; j < numRows; j++)
                {
                    normal = DisplayedObject.GetNormal(i, j);
                    vertices.Add(new VertexPositionNormalTexture(
                                     new Vector3(i * DisplayedObject.GetSpacingX(), DisplayedObject.Heights[i, j], j * DisplayedObject.GetSpacingZ()),
                                     normal,
                                     new Vector2(i, j)));
                }
            }
            for (int i = 0; i < numColumns - 1; i++)
            {
                for (int j = 0; j < numRows - 1; j++)
                {
                    for (int k = DisplayedObject.QuadTriangles.Length - 1; k >= 0; k--)
                    {
                        switch (DisplayedObject.QuadTriangles[k])
                        {
                            case 0:
                                indices.Add(numRows * j + i);
                                break;
                            case 1:
                                indices.Add(numRows * j + i + 1);
                                break;
                            case 2:
                                indices.Add(numRows * (j + 1) + i);
                                break;
                            case 3:
                                indices.Add(numRows * (j + 1) + i + 1);
                                break;
                        }
                    }
                }
            }
        }

        #endregion

        #region IModelo Members


        public int GetParentBoneIndex(int meshNumber)
        {
            return 0;
        }

        #endregion
    }
}
